package cn.silver.framework.mybatis.controller;

import cn.silver.framework.core.validate.QueryGroup;
import cn.silver.framework.log.annotation.Log;
import cn.silver.framework.log.enums.OperateEnums;
import cn.silver.framework.mybatis.bean.BaseBean;
import cn.silver.framework.mybatis.bean.TreeBean;
import cn.silver.framework.mybatis.domain.TreeEntity;
import cn.silver.framework.mybatis.param.TreeParam;
import cn.silver.framework.mybatis.service.ITreeService;
import cn.silver.framework.openapi.model.Result;
import cn.silver.framework.openapi.model.ResultTree;
import cn.silver.framework.web.model.TreeResult;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zhouxiaobo
 */
@Slf4j
public abstract class TreeController<S extends ITreeService<T, P, V>, T extends TreeEntity, P extends TreeParam, V extends TreeBean>
        extends BusController<S, T, P, V> {

    /**
     * 查询树结构数据
     *
     * @param param 查询条件
     * @return 查询结果
     */
    @GetMapping("/tree")
    @Log(operate = OperateEnums.SEAR_TREE)
    @Operation(summary = "获取树结构数据", description = "获取获取树结构数据")
    public ResultTree<V> tree(@Validated(QueryGroup.class) @ModelAttribute P param) {
        this.checkPermission("list");
        if (param.getExpand().equals(Boolean.TRUE)) {
            ResultTree<V> result = new ResultTree<>();
            List<V> models = this.baseService.selectList(param);
            Map<String, List<V>> modelMap = models.stream().collect(Collectors.groupingBy(V::getPid));
            models.stream().filter(item -> modelMap.containsKey(item.getId())).forEach(item -> item.setChildren(modelMap.get(item.getId())));
            result.setKeys(models.stream().filter(item -> CollectionUtils.isNotEmpty(item.getChildren())).map(BaseBean::getId).toList());
            result.setData(models.stream().filter(item -> TreeEntity.ROOT_NODE.equalsIgnoreCase(item.getPid())).toList());
            return result;
        } else {
            return this.rootList(param);
        }
    }

    /**
     * 查询根节点数据
     *
     * @param param 查询条件
     * @return 查询结果集
     */
    @GetMapping("/root")
    @Log(operate = OperateEnums.SEAR_ROOT)
    @Operation(summary = "获取根节点", description = "获取根节点数据")
    public ResultTree<V> rootList(@Validated(QueryGroup.class) @ModelAttribute P param) {
        ResultTree<V> result = new ResultTree<>();
        this.checkPermission("list");
        param.setPid(TreeEntity.ROOT_NODE);
        List<V> models = this.baseService.selectList(param);
        models.forEach(item -> item.setHasChild(true));
        result.setData(models);
        return result;
    }

    /**
     * 查询子节点
     *
     * @param pid   归属父节点
     * @param param 查询条件
     * @return 查询结果集
     */
    @GetMapping("/child/{pid}")
    @Log(operate = OperateEnums.SEAR_CHILD)
    @Operation(summary = "获取根节点", description = "获取根节点数据")
    public Result<List<V>> getChildren(@PathVariable String pid, @Validated(QueryGroup.class) @ModelAttribute P param) {
        this.checkPermission("list");
        param.setPid(pid);
        List<V> models = this.baseService.selectList(param);
        models.forEach(item -> item.setHasChild(true));
        return Result.ok("查询成功", models);
    }

    /**
     * 查询树结构选择列表
     *
     * @param param 查询条件
     * @return 查询结果
     */
    @GetMapping("/treeselect")
    @Operation(summary = "获取下拉树列表")
    public Result<TreeResult> treeselect(@ModelAttribute P param) {
        TreeResult result = this.baseService.getTreeSelect(param);
        return Result.ok("查询成功", result);
    }
}
